package org.springleaf.core.mvc.service.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springleaf.core.mvc.dao.BaseDao;
import org.springleaf.core.mvc.dao.impl.SimpleBaseDaoImpl;
import org.springleaf.core.mvc.service.BaseService;
import org.springleaf.core.query.PageList;
import org.springleaf.core.query.QueryObject;
import org.springleaf.utils.ClassUtils;
import org.springleaf.utils.SpringBeanFactoryUtils;

@SuppressWarnings({ "rawtypes", "unchecked" })
@Transactional(rollbackFor=Exception.class)//Exception也回滚
public abstract class SimpleBaseServiceImpl<T> implements BaseService<T>{
	
	private Class<T> type = null;//model的类型
	private BaseDao baseDao = null;
	
	public SimpleBaseServiceImpl(){
		this.type = ClassUtils.getGeneric(this);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public T get(Serializable id) {
		return getBaseDao().get(this.type,id);
	}

	public Object save(T obj) {
		return getBaseDao().save(obj);
	}

	public void delete(T obj) {
		getBaseDao().delete(obj);
	}
	
	public void delete(Serializable id) {
		T obj = this.get(id);
		if(obj != null){
			delete(obj);
		}
	}

	public void update(T obj) {
		getBaseDao().update(obj);
	}
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public PageList<T> query(QueryObject qo) {
		String where = qo.getQuery();
		String name = this.type.getSimpleName();
		Object [] params = qo.getParameters().toArray();
		
		String hql = "select obj from " + name + " obj where 1 = 1 and " + where;
		List list = getBaseDao().queryAsRow(hql, qo.getCurrentPage() * qo.getPageSize(), qo.getPageSize(), params);
		
		hql = "select count(obj) from " + name + " obj where 1 = 1 and " + where;
		Long total = (Long) getBaseDao().get(hql, params);
		
		PageList<T> pageList = new PageList<T>(Integer.parseInt(total.toString()), list);
		return pageList;
	}

	/**
	 * 得到BaseDao(具体类型是根据域模型名称加"Dao"的spring bean)
	 */
	protected BaseDao getBaseDao(){
		if(this.baseDao == null){
			SessionFactory sessionFactory = SpringBeanFactoryUtils.getBean(SessionFactory.class);
			SimpleBaseDaoImpl daoImpl = new SimpleBaseDaoImpl();
			daoImpl.setSessionFactory(sessionFactory);
			this.baseDao = daoImpl;
		}
		return this.baseDao;
	}
}
